package ru.MatrosovaNastya;

import java.util.*;

/**
 * Created by Анастасия on 28.03.2014.
 */
public class LinkedDeque extends AbstractCollection<Integer> implements Deque<Integer> {

    private class Node {
        private Integer value;
        private Node prev;
        private Node next;


        public Node(int value) {
            this.value = value;
            this.next = null;
            this.prev = null;
        }

        private Node(Integer value, Node prev, Node next) {
            this.value = value;
            this.prev = prev;
            this.next = next;
        }


    }

    private Node tail;
    private Node head;
    private Node current;
    private int size;

    public Iterator<Integer> iterator() {
        throw new UnsupportedOperationException();
    }

    /**
     * Show the size of the deque.
     *
     * @return size
     */
    public int size() {
        return size;
    }


    /**
     * Puts the element at the front of this deque
     *
     * @param value
     */
    @Override
    public void addFirst(Integer value) {

        if (head == null) {
            head = tail = new Node(value);
        } else {
            head = new Node(value, null, head);
            head.next.prev = this.head;
        }
        size++;


    }

    /**
     * Puts the element at the end of this deque
     *
     * @param value
     */
    @Override
    public void addLast(Integer value) {


        if (tail == null) {
            head = tail = new Node(value);
        } else {
            tail = new Node(value, tail, null);
            tail.prev.next = this.tail;
        }

        size++;

    }

    /**
     * Return and delete the first element of this deque
     *
     * @return head of this deque
     */
    @Override
    public Integer pollFirst() {
        if (head == null) {
            return null;
        }

        Integer res = head.value;
        head = head.next;
        if (head != null) {
            head.prev = null;
        }
        size--;
        return res;

    }

    /**
     * Return and delete the last element of this deque
     *
     * @return tail of this deque
     */
    @Override
    public Integer pollLast() {
        if (tail == null) {
            return null;
        }

        Integer res = tail.value;
        tail = tail.prev;
        if (tail != null) {
            tail.next = null;
        }
        size--;
        return res;

    }

    /**
     * Return the first element of this deque
     *
     * @return head of this deque
     * @throws java.util.NoSuchElementException if this deque is empty
     */
    @Override
    public Integer getFirst() {
        if (head == null) throw new NoSuchElementException();
        Integer res = peekFirst();
        return res;
    }

    /**
     * Return the last element of this deque
     *
     * @return tail of this deque
     * @throws java.util.NoSuchElementException if this deque is empty
     */
    @Override
    public Integer getLast() {
        if (head == null) throw new NoSuchElementException();
        Integer res = peekLast();
        return res;
    }

    /**
     * Return the first element of this deque
     *
     * @return the head of this deque or null if deque is empty
     */
    @Override
    public Integer peekFirst() {
        if (head == null) {
            return null;
        } else {
            return head.value;
        }
    }

    /**
     * Return the last element of this deque
     *
     * @return the tail of this deque or null if deque is empty
     */
    @Override
    public Integer peekLast() {
        if (tail == null) {
            return null;
        } else {
            return tail.value;
        }
    }

    /**
     * Finds out whether the stack is empty or not
     * @return true or false
     */
    public boolean isEmpty() {
        return head == null;
    }

    /**
     * Delete all of the elements in this deque
     */
    public void clear() {
        head = null;
        tail = null;
        size = 0;
    }

    /**
     * Return a string representation of this deque
     * @return the string of the elements in this deque
     */
    public String toString() {
        /*String res = "";
        // StringBuilder
        for (int i =0; i < size; i++){
            res += " " + head.value + ",";
            this.head = head.next;

        }*/
        StringBuilder res = new StringBuilder();
        for (current = head; current != null; current = current.next) {
            res.append(current.value);
            res.append(", ");
            // current = head.next;
        }
        return res.toString();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param o
     */
    @Override
    public boolean removeFirstOccurrence(Object o) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param o
     */
    @Override
    public boolean removeLastOccurrence(Object o) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param integer
     */
    @Override
    public boolean offer(Integer integer) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer remove() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer poll() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer element() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer peek() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param integer
     */
    @Override
    public void push(Integer integer) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer pop() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Iterator<Integer> descendingIterator() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param integer
     */
    @Override
    public boolean offerFirst(Integer integer) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     * @param integer
     */
    @Override
    public boolean offerLast(Integer integer) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer removeFirst() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not implemented
     * @throws java.lang.UnsupportedOperationException
     */
    @Override
    public Integer removeLast() {
        throw new UnsupportedOperationException();
    }


}
